package amd64

import (
	"strings"
)

var _ = (TextNode)(AssignKind{})
var _ = (TextNode)(StackAllocKind{})
var _ = (TextNode)(StackFreeKind{})
var _ = (TextNode)(StackVarMovKind{})
var _ = (TextNode)(FuncKind{})
var _ = (TextNode)(AmExprKind{})
var _ = (TextNode)(VarMovKind{})

// 赋值组合指令
type AssignKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewAssignKind(nodes []TextNode) AssignKind {
	var ret AssignKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text AssignKind) Type() TextTypeEnum {
	return ASSIGN
}

func (text AssignKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.AssignKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text AssignKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;AssignKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";AssignKind\n")
	return buf.String()
}

func (text AssignKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// 栈分配组合指令
type StackAllocKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewStackAllocKind(nodes []TextNode) StackAllocKind {
	var ret StackAllocKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text StackAllocKind) Type() TextTypeEnum {
	return StackAlloc
}

func (text StackAllocKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.StackAllocKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text StackAllocKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;StackAllocKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";StackAllocKind\n")
	return buf.String()
}

func (text StackAllocKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// 栈释放组合指令
type StackFreeKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewStackFreeKind(nodes []TextNode) StackFreeKind {
	var ret StackFreeKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text StackFreeKind) Type() TextTypeEnum {
	return StackFree
}

func (text StackFreeKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.StackFreeKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text StackFreeKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;StackFreeKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";StackFreeKind\n")
	return buf.String()
}

func (text StackFreeKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// 栈变量mov组合指令
type StackVarMovKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewStackVarMovKind(nodes []TextNode) StackVarMovKind {
	var ret StackVarMovKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text StackVarMovKind) Type() TextTypeEnum {
	return StackVarMov
}

func (text StackVarMovKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.StackVarMovKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text StackVarMovKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;StackVarMovKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";StackVarMovKind")
	return buf.String()
}

func (text StackVarMovKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// isIsManyKind判断指令节点，是不是不会被重复计算的，使用虚拟寄存器的，组合指令
// - text被判断的指令节点
func isManyKind(text TextNode) bool {
	enum := text.Type()
	if enum > MinMany && enum < MaxMany && enum != AmExpr && enum != Func {
		return true
	}
	return false
}

// 函数组合指令
type FuncKind struct {
	vreg_use_table vregUseTable
	nodes          [][]TextNode
	vreg_use_info  VRegUseInfo
}

func NewFuncKind(nodes [][]TextNode) FuncKind {
	var ret FuncKind
	ret.nodes = nodes
	ret.vreg_use_table = newvregUseTable()
	for i := 0; i < len(nodes); i++ {
		for j := 0; j < len(nodes[i]); j++ {
			ret.vreg_use_info = ret.vreg_use_info.Add(retTextNodeVRegUseInfo(nodes[i], ret.vreg_use_table))
		}
	}
	return ret
}

func (text FuncKind) Type() TextTypeEnum {
	return Func
}

func (text FuncKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.FuncKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		for j := 0; j < len(text.nodes[i]); j++ {
			buf.WriteString(text.nodes[i][j].String())
			buf.WriteString("\n")
		}
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text FuncKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;FuncKind \n")
	for i := 0; i < len(text.nodes); i++ {
		for j := 0; j < len(text.nodes[i]); j++ {
			buf.WriteString(text.nodes[i][j].Asm())
			buf.WriteString("\n")
		}
	}
	buf.WriteString(";FuncKind\n")
	return buf.String()
}

func (text FuncKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// 运算组合指令
type AmExprKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewAmExprKind(nodes []TextNode) AmExprKind {
	var ret AmExprKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text AmExprKind) Type() TextTypeEnum {
	return AmExpr
}

func (text AmExprKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.AmExprKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text AmExprKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;AmExprKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";AmExprKind\n")
	return buf.String()
}

func (text AmExprKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}

// 变量mov组合指令
type VarMovKind struct {
	nodes         []TextNode
	vreg_use_info VRegUseInfo
}

func NewVarMovKind(nodes []TextNode) VarMovKind {
	var ret VarMovKind
	ret.nodes = nodes
	ret.vreg_use_info = retTextNodeVRegUseInfo(nodes, newvregUseTable())
	return ret
}

func (text VarMovKind) Type() TextTypeEnum {
	return VarMov
}

func (text VarMovKind) String() string {
	var buf strings.Builder
	buf.WriteString("amd64.VarMovKind{\n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].String())
		buf.WriteString("\n")
	}
	buf.WriteString(text.vreg_use_info.string())
	buf.WriteString("}\n")
	return buf.String()
}

func (text VarMovKind) Asm() string {
	var buf strings.Builder
	buf.WriteString("\t;VarMovKind \n")
	for i := 0; i < len(text.nodes); i++ {
		buf.WriteString(text.nodes[i].Asm())
		buf.WriteString("\n")
	}
	buf.WriteString(";VarMovKind")
	return buf.String()
}

func (text VarMovKind) GetVRegUseInfo() VRegUseInfo {
	return text.vreg_use_info
}
